package top.codedance.iotp.client.plugins.sync.com;

import top.codedance.iotp.client.plugins.sync.com.bean.ComConnectParam;
import top.codedance.iotp.client.plugins.sync.com.listenner.SerialPortListener;
import com.fazecast.jSerialComm.SerialPort;
import org.ini4j.Ini;
import org.ini4j.Wini;

import java.util.HashMap;
import java.util.Map;

public class ComClient {

    private static Map<Integer, SerialPort> mSerialPorts = new HashMap<>();
    private SerialPort mSerialPort;
    private ComExecuterImpl cei;
    private ComConnectParam comConnectParam;
    private Integer clientId;
    private int sendCount = 0;
    private Wini ini = null;

    public ComClient(ComExecuterImpl cei, Integer clientId, Wini ini){
        this.cei = cei;
        this.clientId = clientId;
        this.ini = ini;
        if(!mSerialPorts.containsKey(clientId)) {
            initConfig();
            connect();
        }
        mSerialPort = mSerialPorts.get(clientId);
        if(mSerialPort == null || !mSerialPort.isOpen()){
            mSerialPorts.remove(clientId);
            initConfig();
            connect();
        }
    }

    private void initConfig(){
        String comName = null;
        int baudRate = 9600, dataBits = 8, stopBits = 1, parity = 0;
        if (ini != null && ini.containsKey("com")) {
            Ini.Section section = ini.get("com");
            if (section.containsKey("comName." + clientId)) {
                comName = section.get("comName." + clientId);
            }
            if (section.containsKey("baudRate." + clientId)) {
                baudRate = Integer.parseInt(section.get("baudRate." + clientId));
            }
            if (section.containsKey("dataBits." + clientId)) {
                dataBits = Integer.parseInt(section.get("dataBits." + clientId));
            }
            if (section.containsKey("stopBits." + clientId)) {
                stopBits = Integer.parseInt(section.get("stopBits." + clientId));
            }
            if (section.containsKey("parity." + clientId)) {
                parity = Integer.parseInt(section.get("parity." + clientId));
            }
            comConnectParam = new ComConnectParam(comName, baudRate, dataBits, stopBits, parity);
        }else{
            comConnectParam = null;
        }
    }

    private void connect(){
        mSerialPort = SerialPort.getCommPort(comConnectParam.getComName());
        mSerialPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
        mSerialPort.setComPortParameters(comConnectParam.getBaudRate(), comConnectParam.getDataBits(), comConnectParam.getStopBits(), comConnectParam.getParity());
        mSerialPort.addDataListener(new SerialPortListener(this));
        if (!mSerialPort.openPort(0, 1024*1024*2, 1024*1024*2)) {
            mSerialPort = null;
        }
        mSerialPorts.put(clientId, mSerialPort);
        System.out.println("Com client is running!");
    }

    public void close(){
        if(mSerialPort != null && mSerialPort.isOpen()) {
            mSerialPort.closePort();
        }
    }

    public boolean isOpen(){
        return mSerialPort.isOpen();
    }

    /**
     * 发送数据
     * @param bytes
     */
    public void send(byte[] bytes){
        if(mSerialPort == null || !mSerialPort.isOpen()) {
            connect();
        }else{
            if(sendCount > 3){
                close();
                connect();
            }
        }
        if(mSerialPort != null && mSerialPort.isOpen()) {
            mSerialPort.writeBytes(bytes, bytes.length);
        }
    }

    /**
     * 添加数据到调用者
     * @param data
     */
    public void appendResult(byte[] data){
        cei.appendResult(data);
        sendCount = 0;
    }
}
